package com.lj.universalframework.http

import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext

/**
 * Created by PengFeifei on 2019-12-24.
 *
 * https://juejin.im/post/5d4d17e5f265da039401f6ea
 */

class ViewModelDsl<Response> {

    //请求条件
    internal lateinit var request: suspend () -> Response
    //开始请求
    internal var onStart: (() -> Unit)? = null
    //响应
    internal var onResponse: ((Response) -> Unit)? = null
    //请求异常
    internal var onError: ((Exception) -> Unit)? = null
    //完成，无论失败与成功
    internal var onFinally: (() -> Unit)? = null


    infix fun onStart(onStart: (() -> Unit)?) {
        this.onStart = onStart
    }


    infix fun onRequest(request: suspend () -> Response) {
        this.request = request
    }

    infix fun onResponse(onResponse: ((Response) -> Unit)?) {
        this.onResponse = onResponse
    }

    infix fun onError(onError: ((Exception) -> Unit)?) {
        this.onError = onError
    }

    infix fun onFinally(onFinally: (() -> Unit)?) {
        this.onFinally = onFinally
    }


    internal fun launch(viewModelScope: CoroutineScope) {
        // 直接开启一个协程，最常见的.launch
        // 在生命周期走到 onCreate 以后，开启此协程内容 .launchWhenCreated
        // 在生命周期走到 onStart 以后，开启此协程内容.launchWhenStarted
        // 在生命周期走到 onResume 以后，开启此协程内容.launchWhenResumed
        viewModelScope.launch(context = Dispatchers.Main) {
            onStart?.invoke()
            try {
                val response = withContext(Dispatchers.IO) {
                    request()
                }
                onResponse?.invoke(response)
            } catch (e: Exception) {
                e.printStackTrace()
                onError?.invoke(e)
            } finally {
                onFinally?.invoke()
            }
        }
    }
}